<!DOCTYPE html>
<html lang="zh" dir="ltr">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ansible自动化运维 – 邵晨峰的博客</title>
    


  
  <script defer src="/js/fuse.min.c4bee9a8d44273d6154fe86006923d4131eb2e8069d8897687137c6f37f553e3.js"></script>



<script src="/js/enquire.min.aa37bdcb743826eecdae5c5d177fc7d6552340f1b4378ffaa9c82b2c6111400b.js"></script>

<script defer src="/js/lazysizes.min.5e11d056075a05065b9c0bfec44084a113fc2976c2952ec804dedb61c7662db9.js"></script>

<script defer src="/js/helper/getParents.min.ccd45f158c1b17849307ba913a72beac239c410f2b6e648496a79842da84e55b.js"></script>

<script defer src="/js/helper/fadeinout.min.9fb19682560d5fa5596fffec85da605067c4acc86aad05add4d8fff9d362a446.js"></script>

<script>
  "use strict";
  
  
  var targetProtocol = "http:"; 
  if (window.location.protocol != targetProtocol)
    window.location.href = targetProtocol + window.location.href.substring(window.location.protocol.length);

  
  function baiduSearch(event) {
    var evt = window.event || event;
        if (evt.keyCode == 13) {
          console.log(event)
          var val = document.getElementById("search").value
          if(!val){
                  alert('搜索内容为空，请输入');
                  return false;
          }else{
            val = val + " site:shaochenfeng.com"
            window.open("https://www.baidu.com/s?ie=utf-8&wd=" + val);
          }
        }
  }

  window.onload = function() {
    
    var languagedir = JSON.parse("\"ltr\"");
    
    var baseurl = JSON.parse("\"http://shaochenfeng.com\"");
    
    var permalink = JSON.parse("\"http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/\"");

    
    var toggleSidebarElem = document.getElementById("toggle-sidebar");
    var toggleMenuElem = document.getElementById("toggle-menu");
    var tocBodyElem = document.querySelector('.toc__body');
    var tocLabelElem = document.querySelector('.toc__label');
    var listMainElem = document.getElementById('list-main');
    var listSideElem = document.getElementById('list-side');
    var singleMenuElem = document.getElementById('single-menu');
    var sliderIcons = document.querySelectorAll('.slider__icon');

    toggleSidebarElem ?
      toggleSidebarElem.addEventListener('change', function (e) {
        if (e.target.checked) {
          if (tocBodyElem) {
            fadeIn(tocBodyElem, 200);
          }
          if (tocLabelElem) {
            fadeIn(tocLabelElem, 200);
          }
          if (listMainElem && listSideElem) {
            listMainElem.className = 'm';
            listSideElem.className = 'r';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });

        } else {
          if (tocBodyElem) {
            fadeOut(tocBodyElem, 200);
          }
          if (tocLabelElem) {
            fadeOut(tocLabelElem, 200);
          }
          if (listMainElem && listSideElem) {
            listMainElem.className = 'mr';
            listSideElem.className = 'hide';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });
        }
      }) : null;

    toggleMenuElem ?
      toggleMenuElem.addEventListener('change', function (e) {
        if (e.target.checked) {
          if (listMainElem && singleMenuElem) {
            listMainElem.className = 'm';
            singleMenuElem.className = 'l';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });

        } else {
          if (listMainElem && singleMenuElem) {
            listMainElem.className = 'lm';
            singleMenuElem.className = 'hide';
          }

          sliderIcons && sliderIcons.forEach(function (elem) {
            if (elem.classList.contains('hide')) {
              elem.classList.remove('hide');
            } else {
              elem.classList.add('hide');
            }
          });
        }
      }) : null;
    


    
    var navCollapseBtn = document.getElementById('navCollapseBtn');
    navCollapseBtn ? navCollapseBtn.addEventListener('click', function(e) {
      var navCollapse = document.querySelector('.navbar__collapse');
      
      if (navCollapse) {
        var dataOpen = navCollapse.getAttribute('data-open');

        if (dataOpen === 'true') {
          navCollapse.setAttribute('data-open', 'false');
          navCollapse.style.maxHeight = 0;
        } else {
          navCollapse.setAttribute('data-open', 'true');
          navCollapse.style.maxHeight = navCollapse.scrollHeight + "px";
        }
      }
    }) : null;
    


    
    var expandBtn = document.querySelectorAll('.expand__button');

    for (let i = 0; i < expandBtn.length; i++) {
      expandBtn[i].addEventListener("click", function () {
        var content = this.nextElementSibling;
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
          this.querySelector('svg').classList.add('expand-icon__right');
          this.querySelector('svg').classList.remove('expand-icon__down');
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
          this.querySelector('svg').classList.remove('expand-icon__right');
          this.querySelector('svg').classList.add('expand-icon__down');
        }
      });
    }
    



    
    document.querySelectorAll('.tab') ? 
    document.querySelectorAll('.tab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var tabLinks = elem.querySelectorAll('.tab__link');
      var tabContents = elem.querySelectorAll('.tab__content');
      var ids = [];

      tabLinks && tabLinks.length > 0 ?
      tabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                tabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              tabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    


    
    document.querySelectorAll('.codetab') ? 
    document.querySelectorAll('.codetab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var codetabLinks = elem.querySelectorAll('.codetab__link');
      var codetabContents = elem.querySelectorAll('.codetab__content');
      var ids = [];

      codetabLinks && codetabLinks.length > 0 ?
      codetabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                codetabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              codetabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    

    
    
    
    var enableDarkMode = JSON.parse("true");
    var root = document.getElementById('root');
    var toggleToLightBtn = document.getElementById('toggleToLight');
    var toggleToDarkBtn = document.getElementById('toggleToDark');

    if (!enableDarkMode) {
      root.className = 'theme__light';
      localStorage.setItem('theme', 'light');
    }
    
    if (toggleToDarkBtn) {
      toggleToDarkBtn.onclick = function (e) {
        root.className = 'theme__dark';
        localStorage.setItem('theme', 'dark');
        toggleToLightBtn.className = 'navbar__icons--icon';
        toggleToDarkBtn.className = 'hide';
      }
    }

    if (toggleToLightBtn) {
      toggleToLightBtn.onclick = function (e) {
        root.className = 'theme__light';
        localStorage.setItem('theme', 'light');
        toggleToLightBtn.className = 'hide';
        toggleToDarkBtn.className = 'navbar__icons--icon';
      }
    }

    
    document.querySelectorAll('.menu__list').forEach(function(elem) {
      if (elem.classList.contains('active')) {
        elem.style.maxHeight = elem.scrollHeight + "px"; 
      }
    });
    
    document.querySelectorAll('.menu__title--collapse').forEach(function(elem) {
      elem.addEventListener('click', function (e) {
        var content = this.nextElementSibling;
        var menuTitleIcon = this.querySelector('.menu__title--icon');
        if (!content) {
          return null;
        }

        var parent = elem.parentNode;
        while (parent.classList.contains('menu__list') && parent.classList.contains('active')) {
          parent.style.maxHeight = 100 * parent.children.length + "px";
          parent = parent.parentNode;
        }

        if (content.style.maxHeight) {
          content.style.maxHeight = null;
          content.classList.remove('active');
          menuTitleIcon.classList.add('right');
          
          if (languagedir === 'rtl') {
            menuTitleIcon.classList.remove('downrtl');
          } else {
            menuTitleIcon.classList.remove('down');
          }
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
          content.classList.add('active');
          menuTitleIcon.classList.remove('right');
          
          if (languagedir === 'rtl') {
            menuTitleIcon.classList.add('downrtl');
          } else {
            menuTitleIcon.classList.add('down');
          }
        }
      });
    });
    


    
    var mobileLogo = document.getElementById('mobileLogo');
    var modal = document.getElementById("myModal");
    var drawer = document.getElementById('myDrawer');
    var drawerCloseBtn = document.querySelector('.drawer__close');

    var openDrawer = function() {
      modal.style.opacity = 1;

      if (languagedir === 'rtl') {
        modal.style.right = 0;
        drawer.style.right = 0;
      } else {
        modal.style.left = 0;
        drawer.style.left = 0;
      }
    }

    var closeDrawer = function() {
      modal.style.opacity = 0;

      if (languagedir === 'rtl') {
        drawer.style.right = '-100%';
      } else {
        drawer.style.left = '-100%';
      }

      
      setTimeout(function () {
        if (languagedir === 'rtl') {
          modal.style.right = '-100%';
        } else {
          modal.style.left = '-100%';
        }
      }, 250);
    }

    mobileLogo.onclick = function () {
      openDrawer();
      localStorage.setItem('isDrawerOpen', 'true');
    }

    modal.onclick = function () {
      closeDrawer();
      localStorage.setItem('isDrawerOpen', 'false');
    }

    drawerCloseBtn.onclick = function () {
      closeDrawer();
      localStorage.setItem('isDrawerOpen', 'false');
    }
  


  
    var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
    var tocElem = document.querySelector('.toc');
    var tableOfContentsElem = tocElem ? tocElem.querySelector('#TableOfContents') : null;
    var singleContentsElem = document.querySelector('.single__contents');
    var dataBGImgs = document.querySelectorAll('div[data-bgimg]');

    
    var tocLevels = JSON.parse("null");

    if (tocLevels) {
      tocLevels = tocLevels.toString();
    } else {
      tocLevels = "h1, h2, h3, h4, h5, h6";
    }

    
    var isLandingBgImg = JSON.parse("null");
    
    var isHome = JSON.parse("false");

    function setNavbarBG(scrollTop) {
      if (isHome && isLandingBgImg && Object.keys(isLandingBgImg).length) {
        if (isLandingBgImg.height <= scrollTop) {
          dataBGImgs.forEach(function(elem) {
            elem.setAttribute('data-bgimg', 'false');
          });
        } else {
          dataBGImgs.forEach(function (elem) {
            elem.setAttribute('data-bgimg', 'true');
          });
        }
      }
    }
    setNavbarBG(lastScrollTop);

    window.onscroll = function () {
      var st = window.pageYOffset || document.documentElement.scrollTop;
      if (st > lastScrollTop) { 
        singleContentsElem ? 
        singleContentsElem.querySelectorAll(tocLevels.toString()).forEach(function(elem) {
          if (document.documentElement.scrollTop >= elem.offsetTop) {
            if (tableOfContentsElem) {
              var id = elem.getAttribute('id');
              tocElem.querySelectorAll('a').forEach(function (elem) {
                elem.classList.remove('active');
              });
              tocElem.querySelector('a[href="#' + id + '"]') ? 
              tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;
            }
          }
        }) : null;
        setNavbarBG(st);
      } else { 
        singleContentsElem ? 
        singleContentsElem.querySelectorAll(tocLevels.toString()).forEach(function(elem) {
          if (document.documentElement.scrollTop >= elem.offsetTop) {
            if (tableOfContentsElem) {
              var id = elem.getAttribute('id');
              tocElem.querySelectorAll('a').forEach(function (elem) {
                elem.classList.remove('active');
              });
              tocElem.querySelector('a[href="#' + id + '"]') ? 
              tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;
            }
          }
        }) : null;
        setNavbarBG(st);
      }
      lastScrollTop = st <= 0 ? 0 : st;
    };
    



    
    var mobileSearchInputElem = document.querySelector('#search-mobile');
    var mobileSearchClassElem = document.querySelector('.mobile-search');
    var mobileSearchBtnElem = document.querySelector('#mobileSearchBtn');
    var mobileSearchCloseBtnElem = document.querySelector('#search-mobile-close');
    var mobileSearchContainer = document.querySelector('#search-mobile-container');
    var mobileSearchResultsElem = document.querySelector('#search-mobile-results');
    var htmlElem = document.querySelector('html');

    if (mobileSearchClassElem) {
      mobileSearchClassElem.style.display = 'none';
    }

    mobileSearchBtnElem ? 
    mobileSearchBtnElem.addEventListener('click', function () {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'block';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.focus();
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'hidden';
      }
    }) : null;

    mobileSearchCloseBtnElem ? 
    mobileSearchCloseBtnElem.addEventListener('click', function() {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'none';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.value = '';
      }
      
      if (mobileSearchResultsElem) {
        while (mobileSearchResultsElem.firstChild) {
          mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
        }
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'visible';
      }
    }) : null;

    mobileSearchInputElem ? 
    mobileSearchInputElem.addEventListener('keydown', function(e) {
      if (e.key === 'Escape') {
        if (mobileSearchContainer) {
          mobileSearchContainer.style.display = 'none';
        }
        
        if (mobileSearchInputElem) {
          mobileSearchInputElem.value = '';
        }

        if (mobileSearchResultsElem) {
          while (mobileSearchResultsElem.firstChild) {
            mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
          }
        }
        if (htmlElem) {
          htmlElem.style.overflowY = 'visible';
        }
      }
    }) : null;
  


  
    var localTheme = localStorage.getItem('theme');
    var rootEleme = document.getElementById('root');
    var selectThemeElem = document.querySelectorAll('.select-theme');
    var selectThemeItemElem = document.querySelectorAll('.select-theme__item');
    
    if (localTheme) {
      selectThemeItemElem ? 
      selectThemeItemElem.forEach(function (elem) {
        if (elem.text.trim() === localTheme) {
          elem.classList.add('is-active');
        } else {
          elem.classList.remove('is-active');
        }
      }) : null;
    }

    selectThemeItemElem ? 
    selectThemeItemElem.forEach(function (v, i) {
      v.addEventListener('click', function (e) {
        var selectedThemeVariant = e.target.text.trim();
        localStorage.setItem('theme', selectedThemeVariant);

        rootEleme.removeAttribute('class');
        rootEleme.classList.add(`theme__${selectedThemeVariant}`);
        selectThemeElem.forEach(function(rootElem) {
          rootElem.querySelectorAll('a').forEach(function (elem) {
            if (elem.classList) {
              if (elem.text.trim() === selectedThemeVariant) {
                if (!elem.classList.contains('is-active')) {
                  elem.classList.add('is-active');
                }
              } else {
                if (elem.classList.contains('is-active')) {
                  elem.classList.remove('is-active');
                }
              }
            }
          });
        });

        if (window.mermaid) {
          if (selectedThemeVariant === "dark" || selectedThemeVariant === "hacker") {
            mermaid.initialize({ theme: 'dark' });
            location.reload();
          } else {
            mermaid.initialize({ theme: 'default' });
            location.reload();
          }
        }

        var utterances = document.querySelector('iframe');
        if (utterances) {
          utterances.contentWindow.postMessage({
            type: 'set-theme',
            theme: selectedThemeVariant === "dark" || selectedThemeVariant === "hacker" ? 'photon-dark' : selectedThemeVariant === 'kimbie' ? 'github-dark-orange' : 'github-light',
          }, 'https://utteranc.es');
        }
      });
    }) : null;
  


  
    
    var langprefix = JSON.parse("\"\"");
    var searchResults = null;
    var searchMenu = null;
    var searchText = null;
    
    
    var enableSearchHighlight = JSON.parse("null");
    
    var enableSearch = JSON.parse("true");

    var fuse = null;

    if (enableSearch) {
      (function initFuse() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', baseurl + langprefix + "/index.json");
        xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
        xhr.onload = function () {
          if (xhr.status === 200) {
            fuse = new Fuse(JSON.parse(xhr.response.toString('utf-8')), {
              keys: ['title', 'description', 'content'],
              includeMatches: enableSearchHighlight,
              shouldSort: true,
              threshold: 0.4,
              location: 0,
              distance: 100,
              maxPatternLength: 32,
              minMatchCharLength: 1,
            });
          }
          else {
            console.error(`[${xhr.status}]Error:`, xhr.statusText);
          }
        };
        xhr.send();
      })();
    }
    
    function makeLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      
      var a = document.createElement('a');
      a.innerHTML = obj.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.permalink);

      var descDiv = document.createElement('div');
      descDiv.setAttribute('class', 'search-result__item--desc');
      if (obj.description) {
        descDiv.innerHTML = obj.description.substring(0, 80);
      } else if (obj.content) {
        descDiv.innerHTML = obj.content.substring(0, 80);
      }
      
      li.appendChild(a);
      li.appendChild(descDiv);
      ulElem.appendChild(li);
    }

    function makeHighlightLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      var descDiv = null;

      var a = document.createElement('a');
      a.innerHTML = obj.item.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.item.uri);

      if (obj.matches && obj.matches.length) {
        for (var i = 0; i < obj.matches.length; i++) {
          if ('title' === obj.matches[i].key) {
            a = document.createElement('a');
            a.innerHTML = generateHighlightedText(obj.matches[i].value, obj.matches[i].indices);
            a.setAttribute('class', 'search-result__item--title');
            a.setAttribute('href', obj.item.uri);
          }
          
          if ('description' === obj.matches[i].key) {
            descDiv = document.createElement('div');
            descDiv.setAttribute('class', 'search-result__item--desc');
            descDiv.innerHTML = generateHighlightedText(obj.item.description, obj.matches[i].indices);
          } else if ('content' === obj.matches[i].key) {
            if (!descDiv) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = generateHighlightedText(obj.item.content.substring(0, 80), obj.matches[i].indices);
            }
          } else {
            if (obj.item.description) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.description;
            } else {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.content.substring(0, 80);
            }
          }
        }

        li.appendChild(a);
        if (descDiv) {
          li.appendChild(descDiv);
        }
        if (li) {
          ulElem.appendChild(li);
        }
      }
    }

    function renderSearchResults(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dd is-active');
      
      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dd-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          a.setAttribute('href', result.uri);
          a.setAttribute('class', 'dd-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.title;
          titleDiv.setAttribute('class', 'search-result__item--title');

          var descDiv = document.createElement('div');
          descDiv.setAttribute('class', 'search-result__item--desc');
          if (result.description) {
            descDiv.innerHTML = result.description;
          } else if (result.content) {
            descDiv.innerHTML = result.content.substring(0, 80);
          }

          li.appendChild(titleDiv);
          li.appendChild(descDiv);
          ul.appendChild(a);
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dd-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      
      searchMenu.appendChild(ul);
    }

    function renderSearchHighlightResults(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dd is-active');

      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dd-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.setAttribute('class', 'dd-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'search-result__item--title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'search-result__item--desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'search-result__item--desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 80), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'search-result__item--desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'search-result__item--desc');
                  descDiv.innerHTML = result.item.content.substring(0, 80);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dd-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      searchMenu.appendChild(ul);
    }

    function renderSearchResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var content = document.createElement('div');
      content.setAttribute('class', 'mobile-search__content');

      if (results.length > 0) {
        results.forEach(function (result) {
          var item = document.createElement('a');
          item.setAttribute('href', result.uri);
          item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' +
             result.title + '</div><div class="mobile-search__item--desc">' + 
               (result.description ? result.description.substring(0,40) : result.content.substring(0,40)) +
                '</div></div>';
          content.appendChild(item);
        });
      } else {
        var item = document.createElement('span');
        content.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(content);      
    }

    function renderSearchHighlightResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var ul = document.createElement('div');
      ul.setAttribute('class', 'mobile-search__content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.appendChild(li);
          li.setAttribute('class', 'mobile-search__item');

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'mobile-search__item--title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'mobile-search__item--desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.content.substring(0, 150);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var item = document.createElement('span');
        ul.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(ul);
    }

    function generateHighlightedText(text, regions) {
      if (!regions) {
        return text;
      }

      var content = '', nextUnhighlightedRegionStartingIndex = 0;

      regions.forEach(function(region) {
        if (region[0] === region[1]) {
          return null;
        }
        
        content += '' +
          text.substring(nextUnhighlightedRegionStartingIndex, region[0]) +
          '<span class="search__highlight">' +
            text.substring(region[0], region[1] + 1) +
          '</span>' +
        '';
        nextUnhighlightedRegionStartingIndex = region[1] + 1;
      });

      content += text.substring(nextUnhighlightedRegionStartingIndex);

      return content;
    };

    var searchElem = document.getElementById('search');
    var searchMobile = document.getElementById('search-mobile');
    var searchResultsContainer = document.getElementById('search-results');

    searchElem ? 
    searchElem.addEventListener('input', function(e) {
      if (!e.target.value | window.innerWidth < 770) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dd') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);

      if (enableSearchHighlight) {
        renderSearchHighlightResults(searchText, results);
      } else {
        renderSearchResults(searchText, results);
      }

      var dropdownItems = searchResultsContainer.querySelectorAll('.dd-item');
      dropdownItems ? dropdownItems.forEach(function (item) {
        item.addEventListener('mousedown', function (e) {
          e.target.click();
        });
      }) : null;
    }) : null;

    searchElem ? 
    searchElem.addEventListener('blur', function() {
      if (window.innerWidth < 770) {
        return null;
      }
      searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dd') : null;
    }) : null;

    searchElem ? 
    searchElem.addEventListener('click', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }
      if (!e.target.value) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dd') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);

      if (enableSearchHighlight) {
        renderSearchHighlightResults(searchText, results);
      } else {
        renderSearchResults(searchText, results);
      }

      var dropdownItems = searchResultsContainer.querySelectorAll('.dd-item');
      dropdownItems ? dropdownItems.forEach(function (item) {
        item.addEventListener('mousedown', function (e) {
          e.target.click();
        });
      }) : null;
    }) : null;

    var searchMenuElem = document.getElementById("search-menu");
    var activeItem = document.querySelector('#search-menu .dd-item.is-active');
    var activeIndex = null;
    var items = null;
    var searchContainerMaxHeight = 350;

    searchElem ? 
    searchElem.addEventListener('keydown', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }

      var items = document.querySelectorAll('#search-menu .dd-item');
      
      if (e.key === 'ArrowDown') {
        if (activeIndex === null) {
          activeIndex = 0;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1;
        }
        items[activeIndex].classList.add('is-active');

        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel > 0) {
          document.querySelector(".search-content").scrollTop += items[activeIndex].getBoundingClientRect().height;
        } else if (activeIndex === 0) {
          document.querySelector(".search-content").scrollTop = 0;
        }
      } else if (e.key === 'ArrowUp') {
        if (activeIndex === null) {
          activeIndex = items.length - 1;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
        }
        items[activeIndex].classList.add('is-active');
        
        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel < 0) {
          document.querySelector(".search-content").scrollTop -= items[activeIndex].getBoundingClientRect().height;
        } else {
          document.querySelector(".search-content").scrollTop = overflowedPixel + items[activeIndex].getBoundingClientRect().height;
        }
      } else if (e.key === 'Enter') {
        var currentItemLink = items[activeIndex].getAttribute('href');
        if (currentItemLink) {
          location.href = currentItemLink;
        }
      } else if (e.key === 'Escape') {
        e.target.value = null;
        if (searchResults) {
          searchResults.classList.remove('is-active');
        }
      }
    }) : null;

    searchMobile ? 
    searchMobile.addEventListener('input', function(e) {
      if (!e.target.value) {
        let wrap = document.getElementById('search-mobile-results');
        while (wrap.firstChild) {
          wrap.removeChild(wrap.firstChild);
        }
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);
      
      if (enableSearchHighlight) {
        renderSearchHighlightResultsMobile(searchText, results);
      } else {
        renderSearchResultsMobile(searchText, results);
      }

      var dropdownItems = searchResultsContainer.querySelectorAll('.dd-item');
      dropdownItems ? dropdownItems.forEach(function (item) {
        item.addEventListener('mousedown', function (e) {
          e.target.click();
        });
      }) : null;
    }) : null;
  
  }
</script>
    


<link rel="stylesheet" href="/css/main.min.css">


    <meta name="description" content="ansible" />
<meta name="keywords" content="">
<meta name="created" content="2020-01-28T00:34:39&#43;0900">
<meta name="modified" content="2020-01-28T00:34:39&#43;0900">


<meta property="og:site_name" content="邵晨峰的博客">
<meta property="og:title" content="ansible自动化运维">
<meta property="og:url" content="http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/">
<meta property="og:type" content="article">

<meta name="generator" content="Hugo 0.81.0" />
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<link rel="canonical" href="http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/">
<link rel="manifest" href="/manifest.json">

  <link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
  <link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
  <link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
  <link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
  <link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
  <link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
  <link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
  <link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
  <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
  <link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
  <link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-512x512.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
  <meta name="msapplication-TileColor" content="#ffffff">
  <meta name="msapplication-TileImage" content="/ms-icon-144x144.png">

    <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "WebPage",
    "headline": "ansible自动化运维",
    "datePublished": "2020-01-28T00:34:39+09:00",
    "dateModified": "2020-01-28T00:34:39+09:00",
    "url" : "http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/",
    "description": "ansible",
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "http://shaochenfeng.com"
    },
    "publisher": {
      "@type": "Organization",
      "name": "邵晨峰的博客",
      "url": "http://shaochenfeng.com"
    }
  }
</script>

    
<script>

var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?bbd1a2ff6319307f954c5233f13dcc26";
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(hm, s);
})();
var _mtac = {};
(function() {
	var mta = document.createElement("script");
	mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4";
	mta.setAttribute("name", "MTAH5");
	mta.setAttribute("sid", "500711551");
	var s = document.getElementsByTagName("script")[0];
	s.parentNode.insertBefore(mta, s);
})();
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>

</head>


<body id="root" class="theme__light">
    <script>
        var rootElem = document.getElementById('root');
        var themeOptions = JSON.parse("[\"light\",\"dark\"]");
        var localTheme = localStorage.getItem('theme');

        if (localTheme) {
            if (themeOptions && themeOptions.length > 0) {
                themeOptions.includes(localTheme) ? 
                rootElem.className = `theme__${localTheme}` :
                rootElem.className = `theme__${themeOptions[0]}`;
            }
        }
    </script>
    
    <div id="container">
        <div id="myDrawer" class="drawer" style="">
  <div class="drawer__header">
    <a href="/" class="drawer__header--text">
      邵晨峰的博客
    </a>
    <div class="grow"></div>
    <div class="drawer__close">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"/></svg>
    </div>
  </div>

  <div class="drawer__body">
    <div class="menu">
  <h6 class="menu__label">
    
    
      ansible自动化运维
    
  </h6>
  <ul>
    
    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="active">
    <a href="http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/"
      class="menu__title active">ansible自动化运维</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="http://shaochenfeng.com/linux/docker%E5%AE%B9%E5%99%A8/"
      class="menu__title ">docker容器</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      linux基础
    </span>
  </li>
  <ul class="menu__list " data-data=/linux%E5%9F%BA%E7%A1%80/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/debian%E7%B3%BB/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      0.debian
    </span>
  </li>
  <ul class="menu__list " data-data=/debian%E7%B3%BB/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
  </ul>
  

      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      0.RHEL
    </span>
  </li>
  <ul class="menu__list " data-data=/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/yum/" class="menu__title " data-depth="1">yum</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/%E5%85%B3%E9%97%ADselinux/" class="menu__title " data-depth="1">关闭SELinux</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/%E5%AF%B9centos-lvm%E9%80%BB%E8%BE%91%E5%88%86%E5%8C%BA%E7%9A%84%E6%89%A9%E5%AE%B9/" class="menu__title " data-depth="1">对centos LVM逻辑分区的扩容</a>
        </li>
      
    
  </ul>
  

      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/1.%E5%9F%BA%E7%A1%80%E5%91%BD%E4%BB%A4/" class="menu__title " data-depth="0">1.基础命令</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/linus%E5%AE%9A%E4%B9%89linux/" class="menu__title " data-depth="0">Linus定义Linux</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/systemd%E5%90%AF%E5%8A%A8%E7%AE%A1%E7%90%86/" class="menu__title " data-depth="0">systemd启动管理</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/tar%E5%91%BD%E4%BB%A4%E5%92%8C%E5%90%84%E7%A7%8D%E5%8E%8B%E7%BC%A9%E6%A0%BC%E5%BC%8F%E7%9A%84%E5%8E%8B%E7%BC%A9%E5%92%8C%E8%A7%A3%E5%8E%8B/" class="menu__title " data-depth="0">tar命令和各种压缩格式的压缩和解压</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/%E4%B8%AD%E6%96%87%E6%97%B6%E5%8C%BA%E7%BC%96%E7%A0%81/" class="menu__title " data-depth="0">中文、时区、编码</a>
        </li>
      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="http://shaochenfeng.com/linux/%E6%95%B0%E6%8D%AE%E5%BA%93/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      数据库
    </span>
  </li>
  <ul class="menu__list " data-data=/%E6%95%B0%E6%8D%AE%E5%BA%93/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/%E6%95%B0%E6%8D%AE%E5%BA%93/mongodb/" class="menu__title " data-depth="0">MongoDB</a>
        </li>
      
    
  </ul>
  

    
  </ul>
</div>



<script>
  var menuTitle = document.querySelectorAll('.menu__title');
  var modal = document.getElementById("myModal");
  var drawer = document.getElementById('myDrawer');

  var closeDrawer = function () {
    setTimeout(function () {
      modal.style.opacity = 0;
      drawer.style.left = '-100%';
      modal.style.left = '-100%';
    }, 250);
  }

  menuTitle ? 
  menuTitle.forEach(function(elem) {
    elem.onclick = function() {
      closeDrawer();
      localStorage.setItem('isDrawerOpen', 'false');
    }
  }) : null;
</script>
  </div>
</div>
<div id="myModal" class="modal" style=""></div>

<script>
  var isDrawerOpen = localStorage.getItem('isDrawerOpen');
  var modal = document.getElementById("myModal");
  var drawer = document.getElementById('myDrawer');
  
  
  var languagedir = JSON.parse("\"ltr\"");

  var openDrawer = function () {
    modal.style.opacity = 1;
    
    if (languagedir === "rtl") {
      modal.style.right = 0;
      drawer.style.right = 0;
    } else {
      modal.style.left = 0;
      drawer.style.left = 0;
    }
  }

  if (isDrawerOpen && isDrawerOpen === 'true') {
    openDrawer();
  }
</script>
        
<nav class="nav">
  <div class="navbar__wrapper" data-bgimg="false">
    <div class="divider">
      <div class="navbar lmr">
        <div id="siteLogo" class="navbar__logo--wrapper">
  
    <a href="/" title="" rel="home" class="navbar__logo--link">
      <img src="/logo.png" alt="Home" class="navbar__logo">
    </a>
  
  
    <a href="/" title="" rel="home" class="navbar__logo--text-link">
      <h6 class="navbar__logo--text" data-bgimg="false">邵晨峰的博客</h6>
    </a>
  
</div>
        
        <div class="navbar__menu--wrapper">
          <div id="tabletLogo" class="hide">
  
  <a href="/" rel="home" class="navbar__logo--link">
    <img src="/logo.png" alt="Home" class="navbar__logo">
  </a>
  
</div>
          <div id="mobileLogo" class="hide">
  <a href="#" class="navbar__logo--link">
    <div class="navbar__icons--icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M4 18h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1s.45 1 1 1zm0-5h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1s.45 1 1 1zM3 7c0 .55.45 1 1 1h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1z"/></svg>
    </div>
  </a>
</div>
          <span id="navMenuMobile" class="hide">
  <button id="navCollapseBtn" class="navbar__dropdown--title" aria-label="Section Menu" data-dir="ltr">
    
      linux
    
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/></svg>
  </button>
  <div class="navbar__collapse" data-open="false">
  <ul>
    

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/blog" class="">博客</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item active">
    <a href="/linux" class="active">linux运维</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/camunda" class="">camunda流程引擎</a>
  </li>

  
  
  
  
  <li class="navbar__menu--mobile-item ">
    <a href="/camunda-cn" class="">camunda中文站</a>
  </li>

  </ul>
</div>
</span>
          <ul id="navMenu" class="navbar__menu">
            

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/blog" data-bgimg="false">博客</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item active">
    <a href="/linux" data-bgimg="false">linux运维</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/camunda" data-bgimg="false">camunda流程引擎</a>
  </li>

  
  
  
  
  <li class="navbar__menu--item ">
    <a href="/camunda-cn" data-bgimg="false">camunda中文站</a>
  </li>

          </ul>
        </div>
        <div class="grow"></div>
        <div id="siteSearch">
          

<div class="search" data-bgimg="false">
  <span class="icon">
    <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
  </span>
  <input id="search" aria-label="Site Search" class="input" type="text" autocomplete="no" onkeydown="baiduSearch(event);" placeholder="搜索">
  <div id="search-results" class="dropdown">
    <div id="search-menu" class="dropdown-menu">
    </div>
  </div>
</div>



        </div>
        <div id="mobileSearch" class="hide">
          
<div id="mobileSearchBtn" class="mobile-search__btn">
  <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
</div>

<div id="search-mobile-container" class="mobile-search hide">
  <div class="mobile-search__top">
    <input id="search-mobile" type="text" aria-label="Mobile Search" placeholder="Search..." class="mobile-search__top--input"/>
    <div id="search-mobile-close" class="mobile-search__top--icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path opacity=".87" fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z"/></svg>
    </div>
  </div>
  <div id="search-mobile-results" class="mobile-search__body">
    
  </div>
</div>

        </div>
        <div class="navbar__icons">
  
  
<button id="toggleToDark" class="navbar__icons--icon" aria-label="Toggle to dark mode">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></svg>
</button>
<button id="toggleToLight" class="navbar__icons--icon" aria-label="Toggle to light mode">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.38 2.019a7.5 7.5 0 1 0 10.6 10.6C21.662 17.854 17.316 22 12.001 22 6.477 22 2 17.523 2 12c0-5.315 4.146-9.661 9.38-9.981z" fill="rgba(255,255,255,1)"/></svg>
</button>
<script>
  var theme = localStorage.getItem('theme');
  var toggleToLightBtn = document.getElementById('toggleToLight');
  var toggleToDarkBtn = document.getElementById('toggleToDark');

  if (theme && theme === 'dark') {
    toggleToLightBtn.className = 'navbar__icons--icon';
    toggleToDarkBtn.className = 'hide';
  } else {
    toggleToLightBtn.className = 'hide';
    toggleToDarkBtn.className = 'navbar__icons--icon';
  }
</script>

  
</div>


      </div>
    </div>
  </div>
</nav>

<script>
  var siteLogo = document.getElementById('siteLogo');
  var tabletLogo = document.getElementById('tabletLogo');
  var mobileLogo = document.getElementById('mobileLogo');
  var navMenu = document.getElementById('navMenu');
  var navMenuMobile = document.getElementById('navMenuMobile');
  var siteSearch = document.getElementById('siteSearch');
  var mobileSearch = document.getElementById('mobileSearch');
  
  enquire.register("screen and (max-width:1280px)", {
    match: function () {
      siteLogo.className = 'navbar__logo--wrapper';
      tabletLogo.className = 'hide';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = '';
      mobileSearch.className = 'hide';
    },
    unmatch: function () {
      siteLogo.className = 'navbar__logo--wrapper';
      tabletLogo.className = 'hide';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = '';
      mobileSearch.className = 'hide';
    },
  }).register("screen and (max-width:960px)", {
    match: function () {
      siteLogo.className = 'hide';
      tabletLogo.className = '';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = 'hide';
      mobileSearch.className = 'navbar__icons--icon';
    },
    unmatch: function () {
      siteLogo.className = 'navbar__logo--wrapper';
      tabletLogo.className = 'hide';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = '';
      mobileSearch.className = 'hide';
    },
  }).register("screen and (max-width:600px)", {
    match: function () {
      siteLogo.className = 'hide';
      tabletLogo.className = 'hide';
      mobileLogo.className = '';
      navMenu.className = 'hide';
      navMenuMobile.className = '';
      siteSearch.className = 'hide';
      mobileSearch.className = 'navbar__icons--icon';
    },
    unmatch: function () {
      siteLogo.className = 'hide';
      tabletLogo.className = '';
      mobileLogo.className = 'hide';
      navMenu.className = 'navbar__menu';
      navMenuMobile.className = 'hide';
      siteSearch.className = 'hide';
      mobileSearch.className = 'navbar__icons--icon';
    },
  });
</script>

        
  <div class="top">
  <div class="header__wrapper bgcolor__header">
    <div class="divider">
      <div class="lmr">
        
      </div>
    </div>
  </div>

  <div class="header__wrapper bgcolor__breadcrumb">
    <div class="divider">
      <div class="lmr flexbox">
        
          <nav class="breadcrumb" aria-label="breadcrumbs" data-is-blog="false">
  
  <ol>
    
  
    
    
  
    
    
  
  <li >
    
      <a href="http://shaochenfeng.com/" class="capitalize">主页</a>
    
  </li>
  
  
  <li >
    
      <a href="http://shaochenfeng.com/linux/" class="capitalize">Linux运维</a>
    
  </li>
  
  
  <li  class="is-active" >
    
      <span>ansible自动化运维</span>
    
  </li>
  
  </ol>


  
</nav>
        
        <div class="grow"></div>
        
        
      </div>
    </div>
  </div>
</div>

        
  

<div class="mid">
  <div class="divider">
    
    <nav id="single-menu" class="l" data-dir="ltr">
      
        <div class="menu">
  
  <ul>
    
    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="active">
    <a href="http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/"
      class="menu__title active">ansible自动化运维</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  <li class="">
    <a href="http://shaochenfeng.com/linux/docker%E5%AE%B9%E5%99%A8/"
      class="menu__title ">docker容器</a>
  </li>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      linux基础
    </span>
  </li>
  <ul class="menu__list " data-data=/linux%E5%9F%BA%E7%A1%80/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/debian%E7%B3%BB/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      0.debian
    </span>
  </li>
  <ul class="menu__list " data-data=/debian%E7%B3%BB/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
  </ul>
  

      
    
      
        
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="1" data-permalink="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      0.RHEL
    </span>
  </li>
  <ul class="menu__list " data-data=/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/yum/" class="menu__title " data-depth="1">yum</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/%E5%85%B3%E9%97%ADselinux/" class="menu__title " data-depth="1">关闭SELinux</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/rhel%E7%BA%A2%E5%B8%BD%E7%B3%BB/%E5%AF%B9centos-lvm%E9%80%BB%E8%BE%91%E5%88%86%E5%8C%BA%E7%9A%84%E6%89%A9%E5%AE%B9/" class="menu__title " data-depth="1">对centos LVM逻辑分区的扩容</a>
        </li>
      
    
  </ul>
  

      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/1.%E5%9F%BA%E7%A1%80%E5%91%BD%E4%BB%A4/" class="menu__title " data-depth="0">1.基础命令</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/linus%E5%AE%9A%E4%B9%89linux/" class="menu__title " data-depth="0">Linus定义Linux</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/systemd%E5%90%AF%E5%8A%A8%E7%AE%A1%E7%90%86/" class="menu__title " data-depth="0">systemd启动管理</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/tar%E5%91%BD%E4%BB%A4%E5%92%8C%E5%90%84%E7%A7%8D%E5%8E%8B%E7%BC%A9%E6%A0%BC%E5%BC%8F%E7%9A%84%E5%8E%8B%E7%BC%A9%E5%92%8C%E8%A7%A3%E5%8E%8B/" class="menu__title " data-depth="0">tar命令和各种压缩格式的压缩和解压</a>
        </li>
      
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/linux%E5%9F%BA%E7%A1%80/%E4%B8%AD%E6%96%87%E6%97%B6%E5%8C%BA%E7%BC%96%E7%A0%81/" class="menu__title " data-depth="0">中文、时区、编码</a>
        </li>
      
    
  </ul>
  

    
      
  
  
  
  
  
  
  

  
  
  
  
  
  
  <li class="menu__title--collapse " data-depth="0" data-permalink="http://shaochenfeng.com/linux/%E6%95%B0%E6%8D%AE%E5%BA%93/">
    <span class="menu__title--icon right">
      
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/></svg>
      
    </span>
    <span class="menu__title--collapse-text">
      数据库
    </span>
  </li>
  <ul class="menu__list " data-data=/%E6%95%B0%E6%8D%AE%E5%BA%93/ data-link=http://shaochenfeng.com/linux/ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4/>
    
      
        
        
        <li>
          <a href="http://shaochenfeng.com/linux/%E6%95%B0%E6%8D%AE%E5%BA%93/mongodb/" class="menu__title " data-depth="0">MongoDB</a>
        </li>
      
    
  </ul>
  

    
  </ul>
</div>


      
    </nav>

    <article id="list-main" class="m" data-dir="ltr">
      <div class="single" data-display="block">
  
  <article class="single__contents" data-dir="ltr">
    <h1 class="title" style="border-bottom: 1px solid currentColor">ansible自动化运维</h1>
    <p>ansible是新出现的自动化运维工具，基于Python开发。</p>
<p>ansible基于模块化工作，本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块，ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents，因为它们是基于ssh来和远程主机通讯的。</p>
<p>ansible目前已经已经被红帽官方收购，是自动化运维工具中大家认可度最高的，并且上手容易，学习简单。是每位运维工程师必须掌握的技能之一。</p>
<h2 id="安装">安装</h2>
<h4 id="使用-pippython的包管理模块安装">使用 pip（python的包管理模块）安装</h4>
<p>　　首先，我们需要安装一个<code>python-pip</code>包，安装完成以后，则直接使用<code>pip</code>命令来安装我们的包，具体操作过程如下：</p>
<pre><code>	yum install python-pip
	pip install ansible
</code></pre><h4 id="使用-yum-安装">使用 yum 安装</h4>
<p>　　yum 安装是我们很熟悉的安装方式了。我们需要先安装一个<code>epel-release</code>包，然后再安装我们的 ansible 即可。</p>
<pre><code>	yum install epel-release -y
	yum install ansible –y
</code></pre><p>安装目录如下(yum安装)：<br />
　　配置文件目录：/etc/ansible/<br />
　　执行文件目录：/usr/bin/<br />
　　Lib库依赖目录：/usr/lib/pythonX.X/site-packages/ansible/<br />
　　Help文档目录：/usr/share/doc/ansible-X.X.X/<br />
　　Man文档目录：/usr/share/man/man1/</p>
<h2 id="ansible-任务执行模式">ansible 任务执行模式</h2>
<p>Ansible 系统由控制主机对被管节点的操作方式可分为两类，即<code>adhoc</code>和<code>playbook</code>：</p>
<ul>
<li>ad-hoc模式(点对点模式)<br />
　　使用单个模块，支持批量执行单条命令。ad-hoc 命令是一种可以快速输入的命令，而且不需要保存起来的命令。<strong>就相当于bash中的一句话shell。</strong></li>
<li>playbook模式(剧本模式)<br />
　　是Ansible主要管理方式，也是Ansible功能强大的关键所在。<strong>playbook通过多个task集合完成一类功能</strong>，如Web服务的安装部署、数据库服务器的批量备份等。可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。</li>
</ul>
<h2 id="配置文件">配置文件</h2>
<p>/etc/ansible/ansible.cfg<br />
~/.ansible.cfg<br />
./ansible.cfg<br />
ANSIBLE_CONFIG 环境变量</p>
<p>hosts主机列表<br />
不改配置的话是/etc/ansible/hosts</p>
<p><code>ansible-config dump</code> 当前应用配置</p>
<h3 id="常见的配置参数">常见的配置参数</h3>
<pre><code>inventory = /etc/ansible/hosts		#这个参数表示资源清单inventory文件的位置
library = /usr/share/ansible		#指向存放Ansible模块的目录，支持多个目录方式，只要用冒号（：）隔开就可以
forks = 5		#并发连接数，默认为5
sudo_user = root		#设置默认执行命令的用户
remote_port = 22		#指定连接被管节点的管理端口，默认为22端口，建议修改，能够更加安全
host_key_checking = False		#设置是否检查SSH主机的密钥，值为True/False。关闭后第一次连接不会提示配置实例
timeout = 60		#设置SSH连接的超时时间，单位为秒
log_path = /var/log/ansible.log		#指定一个存储ansible日志的文件（默认不记录日志）
</code></pre><h3 id="主机列表的写法">主机列表的写法</h3>
<pre><code>1、 直接指明主机地址或主机名：
	## green.example.com#
	# blue.example.com#
	# 192.168.100.1
	# 192.168.100.10
2、 定义一个主机组[组名]把地址或主机名加进去
	[mysql_test]
	192.168.253.159
	192.168.253.160
	192.168.253.153
</code></pre><h2 id="使用点对点模式">使用点对点模式</h2>
<p>例如test是hosts定义的主机组名</p>
<p>ansible &lt;主机组或主机&gt; -m &lt;模块名&gt; -a &lt;模块的参数&gt;<br />
ansible test -a &lsquo;ip a&rsquo;<br />
-K 手动输入sudo密码<br />
-k 手动输入ssh密码<br />
ansible test2 -m debug -a &ldquo;msg={{test}}&rdquo;<br />
ansible test2 -m debug -a &ldquo;msg={{play_hosts}}&rdquo;<br />
ansible test2 -m ping<br />
ansible test2 -l 192.168.56.118 -m shell -a &lsquo;hostname&rsquo; # 指定组中的一个主机</p>
<h2 id="使用剧本模式">使用剧本模式</h2>
<ul>
<li>ansible-playbook a.yml  #执行</li>
<li>ansible-playbook a.yml &ndash;syntax-check    #检查yaml文件的语法是否正确</li>
<li>ansible-playbook a.yml &ndash;list-task       #检查tasks任务</li>
<li>ansible-playbook a.yml &ndash;list-hosts      #检查生效的主机</li>
<li>ansible-playbook a.yml &ndash;start-at-task=&lsquo;Copy Nginx.conf&rsquo;     #指定从某个task开始运行</li>
</ul>
<p>a.yml 如下：</p>
<pre><code>---
- hosts: test
  remote_user: root
  #become: yes # 切换用户执行
  #become_user: zoollcar
  vars:                   # 变量
  - hello: hi,zoollcar
  - service: nginx
  tasks:
  - name: hello
    command: 'echo {{hello}}' # 使用变量
  - name: stop nginx
    service: name=nginx state=stopped
  - name: shell date time # shell模块支持各种shell操作，管道、变量等
    shell: 'echo $(date) &gt;&gt; /tmp/datetime.log'
  - name: command false
    command: 'false'
    ignore_errors: True # 如果命令返回不是0 就会失败回退，用这个可以不强制成功
  - name: make file  # 引用ansible的内部变量、hosts文件中的主机变量
    copy: content=&quot;{{ansible_all_ipv4_addresses}},{{test}}&quot; dest=/tmp/ipv4.txt
</code></pre><h2 id="常见的命令行操作">常见的命令行操作</h2>
<p>ansible-console test2 #交互式执行多个命令</p>
<p>ansible-doc shell # 查看插件的帮助文档<br />
ansible-doc -l # 显示所有的可用插件<br />
ansible-doc -t httpapi -l # 查看所有httpapi相关的插件列表</p>
<p>ansible-galaxy search tomcat # 查找插件<br />
ansible-galaxy install XXX # 安装插件<br />
ansible-galaxy init XXX # 新建插件</p>
<h2 id="ansible-常用模块">ansible 常用模块</h2>
<p>这部分是最重要的，文章来源 <a href="https://www.cnblogs.com/keerya/p/7987886.html">https://www.cnblogs.com/keerya/p/7987886.html</a></p>
<h3 id="1主机连通性测试">1）主机连通性测试</h3>
<p>　　我们使用<code>ansible web -m ping</code>命令来进行主机连通性测试，效果如下：</p>
<pre><code>[root@server ~]# ansible web -m ping
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: false, 
    &quot;ping&quot;: &quot;pong&quot;
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: false, 
    &quot;ping&quot;: &quot;pong&quot;
}
</code></pre><p>　　这样就说明我们的主机是连通状态的。接下来的操作才可以正常进行。</p>
<h3 id="2command-模块">2）command 模块</h3>
<p>　　这个模块可以直接在远程主机上执行命令，并将结果返回本主机。<br />
　　举例如下：</p>
<pre><code>[root@server ~]# ansible web -m command -a 'ss -ntl'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:111                      *:*                  
LISTEN     0      5      192.168.122.1:53                       *:*                  
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      128    127.0.0.1:631                      *:*                  
LISTEN     0      128          *:23000                    *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::111                     :::*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      128        ::1:631                     :::*                  
LISTEN     0      100        ::1:25                      :::*                  

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:111                      *:*                  
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      128    127.0.0.1:631                      *:*                  
LISTEN     0      128          *:23000                    *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::111                     :::*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      128        ::1:631                     :::*                  
LISTEN     0      100        ::1:25                      :::*  
</code></pre><p>　　命令模块接受命令名称，后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理，比如$HOME和操作如&quot;&lt;&quot;，&quot;&gt;&quot;，&quot;|&quot;，&quot;;&quot;，&quot;&amp;&quot; 工作（需要使用（shell）模块实现这些功能）。注意，该命令不支持<code>| 管道命令</code>。<br />
　　下面来看一看该模块下常用的几个命令：</p>
<blockquote>
<p>chdir　　　　　　 # 在执行命令之前，先切换到该目录<br />
executable # 切换shell来执行命令，需要使用命令的绝对路径<br />
free_form 　 # 要执行的Linux指令，一般使用Ansible的-a参数代替。<br />
creates 　# 一个文件名，当这个文件存在，则该命令不执行,可以<br />
用来做判断<br />
removes # 一个文件名，这个文件不存在，则该命令不执行</p>
</blockquote>
<p>　　下面我们来看看这些命令的执行效果：</p>
<pre><code>[root@server ~]# ansible web -m command -a 'chdir=/data/ ls'	#先切换到/data/ 目录，再执行“ls”命令
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
aaa.jpg
fastdfs
mogdata
tmp
web
wKgleloeYoCAMLtZAAAWEekAtkc497.jpg

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
aaa.jpg
fastdfs
mogdata
tmp
web
wKgleloeYoCAMLtZAAAWEekAtkc497.jpg
[root@server ~]# ansible web -m command -a 'creates=/data/aaa.jpg ls'		#如果/data/aaa.jpg存在，则不执行“ls”命令
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
skipped, since /data/aaa.jpg exists

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
skipped, since /data/aaa.jpg exists
[root@server ~]# ansible web -m command -a 'removes=/data/aaa.jpg cat /data/a'		#如果/data/aaa.jpg存在，则执行“cat /data/a”命令
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
hello

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
hello
</code></pre><h3 id="3shell-模块">3）shell 模块</h3>
<p>　　shell模块可以在远程主机上调用shell解释器运行命令，支持shell的各种功能，例如管道等。</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /etc/passwd |grep &quot;keer&quot;'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
keer❌10001:1000:keer:/home/keer:/bin/sh

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
keer❌10001:10001::/home/keer:/bin/sh
</code></pre><p>　　只要是我们的shell命令，都可以通过这个模块在远程主机上运行，这里就不一一举例了。</p>
<h3 id="4copy-模块">4）copy 模块</h3>
<p>　　这个模块用于将文件复制到远程主机，同时支持给定内容生成文件和修改权限等。<br />
　　其相关选项如下：</p>
<blockquote>
<p><code>src</code>　　　　#被复制到远程主机的本地文件。可以是绝对路径，也可以是相对路径。如果路径是一个目录，则会递归复制，用法类似于&quot;rsync&quot;<br />
<code>content</code>　　　#用于替换&quot;src&quot;，可以直接指定文件的值<br />
<code>dest</code>　　　　#必选项，将源文件复制到的远程主机的<strong>绝对路径</strong><br />
<code>backup</code>　　　#当文件内容发生改变后，在覆盖之前把源文件备份，备份文件包含时间信息<br />
<code>directory_mode</code>　　　　#递归设定目录的权限，默认为系统默认权限<br />
<code>force</code>　　　　#当目标主机包含该文件，但内容不同时，设为&quot;yes&quot;，表示强制覆盖；设为&quot;no&quot;，表示目标主机的目标位置不存在该文件才复制。默认为&quot;yes&quot;<br />
<code>others</code>　　　　#所有的 file 模块中的选项可以在这里使用</p>
</blockquote>
<p>用法举例如下：<br />
<strong>① 复制文件：</strong></p>
<pre><code>[root@server ~]# ansible web -m copy -a 'src=~/hello dest=/data/hello' 
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;22596363b3de40b06f981fb85d82312e8c0ed511&quot;, 
    &quot;dest&quot;: &quot;/data/hello&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;md5sum&quot;: &quot;6f5902ac237024bdd0c176cb93063dc4&quot;, 
    &quot;mode&quot;: &quot;0644&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 12, 
    &quot;src&quot;: &quot;/root/.ansible/tmp/ansible-tmp-1512437093.55-228281064292921/source&quot;, 
    &quot;state&quot;: &quot;file&quot;, 
    &quot;uid&quot;: 0
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;22596363b3de40b06f981fb85d82312e8c0ed511&quot;, 
    &quot;dest&quot;: &quot;/data/hello&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;md5sum&quot;: &quot;6f5902ac237024bdd0c176cb93063dc4&quot;, 
    &quot;mode&quot;: &quot;0644&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 12, 
    &quot;src&quot;: &quot;/root/.ansible/tmp/ansible-tmp-1512437093.74-44694985235189/source&quot;, 
    &quot;state&quot;: &quot;file&quot;, 
    &quot;uid&quot;: 0
}
</code></pre><p><strong>② 给定内容生成文件，并制定权限</strong></p>
<pre><code>[root@server ~]# ansible web -m copy -a 'content=&quot;I am keer\n&quot; dest=/data/name mode=666'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;0421570938940ea784f9d8598dab87f07685b968&quot;, 
    &quot;dest&quot;: &quot;/data/name&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;md5sum&quot;: &quot;497fa8386590a5fc89090725b07f175c&quot;, 
    &quot;mode&quot;: &quot;0666&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 10, 
    &quot;src&quot;: &quot;/root/.ansible/tmp/ansible-tmp-1512437327.37-199512601767687/source&quot;, 
    &quot;state&quot;: &quot;file&quot;, 
    &quot;uid&quot;: 0
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;0421570938940ea784f9d8598dab87f07685b968&quot;, 
    &quot;dest&quot;: &quot;/data/name&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;md5sum&quot;: &quot;497fa8386590a5fc89090725b07f175c&quot;, 
    &quot;mode&quot;: &quot;0666&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 10, 
	    &quot;src&quot;: &quot;/root/.ansible/tmp/ansible-tmp-1512437327.55-218104039503110/source&quot;, 
    &quot;state&quot;: &quot;file&quot;, 
    &quot;uid&quot;: 0
}
</code></pre><p>　　我们现在可以去查看一下我们生成的文件及其权限：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ls -l /data/'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
total 28
-rw-rw-rw-   1 root root   12 Dec  6 09:45 name

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
total 40
-rw-rw-rw- 1 root     root       12 Dec  5 09:45 name
</code></pre><p>　　可以看出我们的name文件已经生成，并且权限为666。<br />
<strong>③ 关于覆盖</strong><br />
　　我们把文件的内容修改一下，然后选择覆盖备份：</p>
<pre><code>[root@server ~]# ansible web -m copy -a 'content=&quot;I am keerya\n&quot; backup=yes dest=/data/name mode=666'
192.168.37.122 | SUCCESS =&gt; {
    &quot;backup_file&quot;: &quot;/data/name.4394.2017-12-06@09:46:25~&quot;, 
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;064a68908ab9971ee85dbc08ea038387598e3778&quot;, 
    &quot;dest&quot;: &quot;/data/name&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;md5sum&quot;: &quot;8ca7c11385856155af52e560f608891c&quot;, 
    &quot;mode&quot;: &quot;0666&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 12, 
    &quot;src&quot;: &quot;/root/.ansible/tmp/ansible-tmp-1512438383.78-228128616784888/source&quot;, 
    &quot;state&quot;: &quot;file&quot;, 
    &quot;uid&quot;: 0
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;backup_file&quot;: &quot;/data/name.5962.2017-12-05@09:46:24~&quot;, 
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;064a68908ab9971ee85dbc08ea038387598e3778&quot;, 
    &quot;dest&quot;: &quot;/data/name&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;md5sum&quot;: &quot;8ca7c11385856155af52e560f608891c&quot;, 
    &quot;mode&quot;: &quot;0666&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 12, 
    &quot;src&quot;: &quot;/root/.ansible/tmp/ansible-tmp-1512438384.0-170718946740009/source&quot;, 
    &quot;state&quot;: &quot;file&quot;, 
    &quot;uid&quot;: 0
}
</code></pre><p>　　现在我们可以去查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ls -l /data/'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
total 28
-rw-rw-rw-   1 root root   12 Dec  6 09:46 name
-rw-rw-rw-   1 root root   10 Dec  6 09:45 name.4394.2017-12-06@09:46:25~

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
total 40
-rw-rw-rw- 1 root     root       12 Dec  5 09:46 name
-rw-rw-rw- 1 root     root       10 Dec  5 09:45 name.5962.2017-12-05@09:46:24~
</code></pre><p>　　可以看出，我们的源文件已经被备份，我们还可以查看一下<code>name</code>文件的内容：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /data/name'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
I am keerya

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
I am keerya
</code></pre><p>　　证明，这正是我们新导入的文件的内容。</p>
<h3 id="5file-模块">5）file 模块</h3>
<p>　　该模块主要用于设置文件的属性，比如创建文件、创建链接文件、删除文件等。<br />
　　下面是一些常见的命令：</p>
<blockquote>
<p><code>force</code>　　#需要在两种情况下强制创建软链接，一种是源文件不存在，但之后会建立的情况下；另一种是目标软链接已存在，需要先取消之前的软链，然后创建新的软链，有两个选项：yes|no<br />
<code>group</code>　　#定义文件/目录的属组。后面可以加上<code>mode</code>：定义文件/目录的权限<br />
<code>owner</code>　　#定义文件/目录的属主。后面必须跟上<code>path</code>：定义文件/目录的路径<br />
<code>recurse</code>　　#递归设置文件的属性，只对目录有效，后面跟上<code>src</code>：被链接的源文件路径，只应用于<code>state=link</code>的情况<br />
<code>dest</code>　　#被链接到的路径，只应用于<code>state=link</code>的情况<br />
<code>state</code>　　#状态，有以下选项：</p>
<blockquote>
<p><code>directory</code>：如果目录不存在，就创建目录<br />
<code>file</code>：即使文件不存在，也不会被创建<br />
<code>link</code>：创建软链接<br />
<code>hard</code>：创建硬链接<br />
<code>touch</code>：如果文件不存在，则会创建一个新的文件，如果文件或目录已存在，则更新其最后修改时间<br />
<code>absent</code>：删除目录、文件或者取消链接文件</p>
</blockquote>
</blockquote>
<p>　　用法举例如下：<br />
<strong>① 创建目录：</strong></p>
<pre><code>[root@server ~]# ansible web -m file -a 'path=/data/app state=directory'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;mode&quot;: &quot;0755&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;path&quot;: &quot;/data/app&quot;, 
    &quot;size&quot;: 6, 
    &quot;state&quot;: &quot;directory&quot;, 
    &quot;uid&quot;: 0
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;mode&quot;: &quot;0755&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;path&quot;: &quot;/data/app&quot;, 
    &quot;size&quot;: 4096, 
    &quot;state&quot;: &quot;directory&quot;, 
    &quot;uid&quot;: 0
}
</code></pre><p>　　我们可以查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ls -l /data'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
total 28
drwxr-xr-x   2 root root    6 Dec  6 10:21 app

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
total 44
drwxr-xr-x 2 root     root     4096 Dec  5 10:21 app
</code></pre><p>　　可以看出，我们的目录已经创建完成。<br />
<strong>② 创建链接文件</strong></p>
<pre><code>[root@server ~]# ansible web -m file -a 'path=/data/bbb.jpg src=aaa.jpg state=link'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;dest&quot;: &quot;/data/bbb.jpg&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;mode&quot;: &quot;0777&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 7, 
    &quot;src&quot;: &quot;aaa.jpg&quot;, 
    &quot;state&quot;: &quot;link&quot;, 
    &quot;uid&quot;: 0
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;dest&quot;: &quot;/data/bbb.jpg&quot;, 
    &quot;gid&quot;: 0, 
    &quot;group&quot;: &quot;root&quot;, 
    &quot;mode&quot;: &quot;0777&quot;, 
    &quot;owner&quot;: &quot;root&quot;, 
    &quot;size&quot;: 7, 
    &quot;src&quot;: &quot;aaa.jpg&quot;, 
    &quot;state&quot;: &quot;link&quot;, 
    &quot;uid&quot;: 0
}
</code></pre><p>　　我们可以去查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ls -l /data'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
total 28
-rw-r--r--   1 root root 5649 Dec  5 13:49 aaa.jpg
lrwxrwxrwx   1 root root    7 Dec  6 10:25 bbb.jpg -&gt; aaa.jpg

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
total 44
-rw-r--r-- 1 root     root     5649 Dec  4 14:44 aaa.jpg
lrwxrwxrwx 1 root     root        7 Dec  5 10:25 bbb.jpg -&gt; aaa.jpg
</code></pre><p>　　我们的链接文件已经创建成功。<br />
<strong>③ 删除文件</strong></p>
<pre><code>[root@server ~]# ansible web -m file -a 'path=/data/a state=absent'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;path&quot;: &quot;/data/a&quot;, 
    &quot;state&quot;: &quot;absent&quot;
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;path&quot;: &quot;/data/a&quot;, 
    &quot;state&quot;: &quot;absent&quot;
}
</code></pre><p>　　我们可以查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ls /data/a'
192.168.37.122 | FAILED | rc=2 &gt;&gt;
ls: cannot access /data/a: No such file or directory

192.168.37.133 | FAILED | rc=2 &gt;&gt;
ls: cannot access /data/a: No such file or directory
</code></pre><p>　　发现已经没有这个文件了。<br />
　　</p>
<h3 id="6fetch-模块">6）fetch 模块</h3>
<p>　　该模块用于从远程某主机获取（复制）文件到本地。<br />
　　有两个选项：</p>
<blockquote>
<p><code>dest</code>：用来存放文件的目录<br />
<code>src</code>：在远程拉取的文件，并且必须是一个<strong>file</strong>，不能是<strong>目录</strong></p>
</blockquote>
<p>　　具体举例如下：</p>
<pre><code>[root@server ~]# ansible web -m fetch -a 'src=/data/hello dest=/data'  
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;22596363b3de40b06f981fb85d82312e8c0ed511&quot;, 
    &quot;dest&quot;: &quot;/data/192.168.37.122/data/hello&quot;, 
    &quot;md5sum&quot;: &quot;6f5902ac237024bdd0c176cb93063dc4&quot;, 
    &quot;remote_checksum&quot;: &quot;22596363b3de40b06f981fb85d82312e8c0ed511&quot;, 
    &quot;remote_md5sum&quot;: null
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;checksum&quot;: &quot;22596363b3de40b06f981fb85d82312e8c0ed511&quot;, 
    &quot;dest&quot;: &quot;/data/192.168.37.133/data/hello&quot;, 
    &quot;md5sum&quot;: &quot;6f5902ac237024bdd0c176cb93063dc4&quot;, 
    &quot;remote_checksum&quot;: &quot;22596363b3de40b06f981fb85d82312e8c0ed511&quot;, 
    &quot;remote_md5sum&quot;: null
}
</code></pre><p>　　我们可以在本机上查看一下文件是否复制成功。要注意，文件保存的路径是我们设置的接收目录下的<code>被管制主机ip</code>目录下：</p>
<pre><code>[root@server ~]# cd /data/
[root@server data]# ls
1  192.168.37.122  192.168.37.133  fastdfs  web
[root@server data]# cd 192.168.37.122
[root@server 192.168.37.122]# ls
data
[root@server 192.168.37.122]# cd data/
[root@server data]# ls
hello
[root@server data]# pwd
/data/192.168.37.122/data
</code></pre><h3 id="7cron-模块">7）cron 模块</h3>
<p>　　该模块适用于管理<code>cron</code>计划任务的。<br />
　　其使用的语法跟我们的<code>crontab</code>文件中的语法一致，同时，可以指定以下选项：</p>
<blockquote>
<p><code>day=</code> #日应该运行的工作( 1-31, *, */2, )<br />
<code>hour=</code> # 小时 ( 0-23, *, */2, )<br />
<code>minute=</code> #分钟( 0-59, *, */2, )<br />
<code>month=</code> # 月( 1-12, *, /2, )<br />
<code>weekday=</code> # 周 ( 0-6 for Sunday-Saturday,, )<br />
<code>job=</code> #指明运行的命令是什么<br />
<code>name=</code> #定时任务描述<br />
<code>reboot</code> # 任务在重启时运行，不建议使用，建议使用special_time<br />
<code>special_time</code> #特殊的时间范围，参数：reboot（重启时），annually（每年），monthly（每月），weekly（每周），daily（每天），hourly（每小时）<br />
<code>state</code> #指定状态，present表示添加定时任务，也是默认设置，absent表示删除定时任务<br />
<code>user</code> # 以哪个用户的身份执行</p>
</blockquote>
<p>　　举例如下：<br />
<strong>① 添加计划任务</strong></p>
<pre><code>[root@server ~]# ansible web -m cron -a 'name=&quot;ntp update every 5 min&quot; minute=*/5 job=&quot;/sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null&quot;'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;envs&quot;: [], 
    &quot;jobs&quot;: [
        &quot;ntp update every 5 min&quot;
    ]
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;envs&quot;: [], 
    &quot;jobs&quot;: [
        &quot;ntp update every 5 min&quot;
    ]
}
</code></pre><p>　　我们可以去查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'crontab -l'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null
</code></pre><p>　　可以看出，我们的计划任务已经设置成功了。<br />
<strong>② 删除计划任务</strong><br />
　　如果我们的计划任务添加错误，想要删除的话，则执行以下操作：<br />
　　首先我们查看一下现有的计划任务：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'crontab -l'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null
#Ansible: df everyday
* 15 * * * df -lh &gt;&gt; /tmp/disk_total &amp;&gt; /dev/null

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null
#Ansible: df everyday
* 15 * * * df -lh &gt;&gt; /tmp/disk_total &amp;&gt; /dev/null
</code></pre><p>　　然后执行删除操作：</p>
<pre><code>[root@server ~]# ansible web -m cron -a 'name=&quot;df everyday&quot; hour=15 job=&quot;df -lh &gt;&gt; /tmp/disk_total &amp;&gt; /dev/null&quot; state=absent'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;envs&quot;: [], 
    &quot;jobs&quot;: [
        &quot;ntp update every 5 min&quot;
    ]
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;envs&quot;: [], 
    &quot;jobs&quot;: [
        &quot;ntp update every 5 min&quot;
    ]
}
</code></pre><p>　　删除完成后，我们再查看一下现有的计划任务确认一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'crontab -l'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &amp;&gt; /dev/null
</code></pre><p>　　我们的删除操作已经成功。</p>
<h3 id="8yum-模块">8）yum 模块</h3>
<p>　　顾名思义，该模块主要用于软件的安装。<br />
　　其选项如下：</p>
<blockquote>
<p><code>name=</code>　　#所安装的包的名称<br />
<code>state=</code>　　#<code>present</code>&mdash;&gt;安装， <code>latest</code>&mdash;&gt;安装最新的, <code>absent</code>&mdash;&gt; 卸载软件。<br />
<code>update_cache</code>　　#强制更新yum的缓存<br />
<code>conf_file</code>　　#指定远程yum安装时所依赖的配置文件（安装本地已有的包）。<br />
<code>disable_pgp_check</code>　　#是否禁止GPG checking，只用于<code>present</code>or <code>latest</code>。<br />
<code>disablerepo</code>　　#临时禁止使用yum库。 只用于安装或更新时。<br />
<code>enablerepo</code>　　#临时使用的yum库。只用于安装或更新时。</p>
</blockquote>
<p>　　下面我们就来安装一个包试试看：</p>
<pre><code>[root@server ~]# ansible web -m yum -a 'name=htop state=present'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;msg&quot;: &quot;&quot;, 
    &quot;rc&quot;: 0, 
    &quot;results&quot;: [
        &quot;Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--&gt; Running transaction check\n---&gt; Package htop.x86_64 0:2.0.2-1.el7 will be installed\n--&gt; Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package         Arch              Version                Repository       Size\n================================================================================\nInstalling:\n htop            x86_64            2.0.2-1.el7            epel             98 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 98 k\nInstalled size: 207 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : htop-2.0.2-1.el7.x86_64                                      1/1 \n  Verifying  : htop-2.0.2-1.el7.x86_64                                      1/1 \n\nInstalled:\n  htop.x86_64 0:2.0.2-1.el7                                                     \n\nComplete!\n&quot;
    ]
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;msg&quot;: &quot;Warning: RPMDB altered outside of yum.\n** Found 3 pre-existing rpmdb problem(s), 'yum check' output follows:\nipa-client-4.4.0-12.el7.centos.x86_64 has installed conflicts freeipa-client: ipa-client-4.4.0-12.el7.centos.x86_64\nipa-client-common-4.4.0-12.el7.centos.noarch has installed conflicts freeipa-client-common: ipa-client-common-4.4.0-12.el7.centos.noarch\nipa-common-4.4.0-12.el7.centos.noarch has installed conflicts freeipa-common: ipa-common-4.4.0-12.el7.centos.noarch\n&quot;, 
    &quot;rc&quot;: 0, 
    &quot;results&quot;: [
        &quot;Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--&gt; Running transaction check\n---&gt; Package htop.x86_64 0:2.0.2-1.el7 will be installed\n--&gt; Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package         Arch              Version                Repository       Size\n================================================================================\nInstalling:\n htop            x86_64            2.0.2-1.el7            epel             98 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 98 k\nInstalled size: 207 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : htop-2.0.2-1.el7.x86_64                                      1/1 \n  Verifying  : htop-2.0.2-1.el7.x86_64                                      1/1 \n\nInstalled:\n  htop.x86_64 0:2.0.2-1.el7                                                     \n\nComplete!\n&quot;
    ]
}
</code></pre><p>　　安装成功。</p>
<h3 id="9service-模块">9）service 模块</h3>
<p>　　该模块用于服务程序的管理。<br />
　　其主要选项如下：</p>
<blockquote>
<p><code>arguments</code> #命令行提供额外的参数<br />
<code>enabled</code> #设置开机启动。<br />
<code>name=</code> #服务名称<br />
<code>runlevel</code> #开机启动的级别，一般不用指定。<br />
<code>sleep</code> #在重启服务的过程中，是否等待。如在服务关闭以后等待2秒再启动。(定义在剧本中。)<br />
<code>state</code> #有四种状态，分别为：<code>started</code>&mdash;&gt;启动服务， <code>stopped</code>&mdash;&gt;停止服务， <code>restarted</code>&mdash;&gt;重启服务， <code>reloaded</code>&mdash;&gt;重载配置</p>
</blockquote>
<p>　　下面是一些例子：<br />
<strong>① 开启服务并设置自启动</strong></p>
<pre><code>[root@server ~]# ansible web -m service -a 'name=nginx state=started enabled=true' 
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;enabled&quot;: true, 
    &quot;name&quot;: &quot;nginx&quot;, 
    &quot;state&quot;: &quot;started&quot;, 
    ……
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;enabled&quot;: true, 
    &quot;name&quot;: &quot;nginx&quot;, 
    &quot;state&quot;: &quot;started&quot;, 
    ……
}
</code></pre><p>　　我们可以去查看一下端口是否打开：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ss -ntl'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:80                       *:*                                  

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port                    
LISTEN     0      128          *:80                       *:*                  
</code></pre><p>　　可以看出我们的80端口已经打开。<br />
<strong>② 关闭服务</strong><br />
　　我们也可以通过该模块来关闭我们的服务：</p>
<pre><code>[root@server ~]# ansible web -m service -a 'name=nginx state=stopped'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;name&quot;: &quot;nginx&quot;, 
    &quot;state&quot;: &quot;stopped&quot;, 
	……
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;name&quot;: &quot;nginx&quot;, 
    &quot;state&quot;: &quot;stopped&quot;, 
	……
}
</code></pre><p>　　一样的，我们来查看一下端口：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'ss -ntl | grep 80'
192.168.37.122 | FAILED | rc=1 &gt;&gt;

192.168.37.133 | FAILED | rc=1 &gt;&gt;
</code></pre><p>　　可以看出，我们已经没有80端口了，说明我们的nginx服务已经关闭了。</p>
<h3 id="10user-模块">10）user 模块</h3>
<p>　　该模块主要是用来管理用户账号。<br />
　　其主要选项如下：</p>
<blockquote>
<p><code>comment</code>　　# 用户的描述信息<br />
<code>createhome</code>　　# 是否创建家目录<br />
<code>force</code>　　# 在使用state=absent时, 行为与userdel –force一致.<br />
<code>group</code>　　# 指定基本组<br />
<code>groups</code>　　# 指定附加组，如果指定为(groups=)表示删除所有组<br />
<code>home</code>　　# 指定用户家目录<br />
<code>move_home</code>　　# 如果设置为home=时, 试图将用户主目录移动到指定的目录<br />
<code>name</code>　　# 指定用户名<br />
<code>non_unique</code>　　# 该选项允许改变非唯一的用户ID值<br />
<code>password</code>　　# 指定用户密码<br />
<code>remove</code>　　# 在使用state=absent时, 行为是与userdel –remove一致<br />
<code>shell</code>　　# 指定默认shell<br />
<code>state</code>　　# 设置帐号状态，不指定为创建，指定值为absent表示删除<br />
<code>system</code>　　# 当创建一个用户，设置这个用户是系统用户。这个设置不能更改现有用户<br />
<code>uid</code>　　# 指定用户的uid</p>
</blockquote>
<p>　　举例如下：<br />
<strong>① 添加一个用户并指定其 uid</strong></p>
<pre><code>[root@server ~]# ansible web -m user -a 'name=keer uid=11111'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;comment&quot;: &quot;&quot;, 
    &quot;createhome&quot;: true, 
    &quot;group&quot;: 11111, 
    &quot;home&quot;: &quot;/home/keer&quot;, 
    &quot;name&quot;: &quot;keer&quot;, 
    &quot;shell&quot;: &quot;/bin/bash&quot;, 
    &quot;state&quot;: &quot;present&quot;, 
    &quot;stderr&quot;: &quot;useradd: warning: the home directory already exists.\nNot copying any file from skel directory into it.\nCreating mailbox file: File exists\n&quot;, 
    &quot;system&quot;: false, 
    &quot;uid&quot;: 11111
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;comment&quot;: &quot;&quot;, 
    &quot;createhome&quot;: true, 
    &quot;group&quot;: 11111, 
    &quot;home&quot;: &quot;/home/keer&quot;, 
    &quot;name&quot;: &quot;keer&quot;, 
    &quot;shell&quot;: &quot;/bin/bash&quot;, 
    &quot;state&quot;: &quot;present&quot;, 
    &quot;stderr&quot;: &quot;useradd: warning: the home directory already exists.\nNot copying any file from skel directory into it.\nCreating mailbox file: File exists\n&quot;, 
    &quot;system&quot;: false, 
    &quot;uid&quot;: 11111
}
</code></pre><p>　　添加完成，我们可以去查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /etc/passwd |grep keer'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
keer❌11111:11111::/home/keer:/bin/bash

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
keer❌11111:11111::/home/keer:/bin/bash
</code></pre><p><strong>② 删除用户</strong></p>
<pre><code>[root@server ~]# ansible web -m user -a 'name=keer state=absent'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;force&quot;: false, 
    &quot;name&quot;: &quot;keer&quot;, 
    &quot;remove&quot;: false, 
    &quot;state&quot;: &quot;absent&quot;
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;force&quot;: false, 
    &quot;name&quot;: &quot;keer&quot;, 
    &quot;remove&quot;: false, 
    &quot;state&quot;: &quot;absent&quot;
}
</code></pre><p>　　一样的，删除之后，我们去看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /etc/passwd |grep keer'
192.168.37.122 | FAILED | rc=1 &gt;&gt;

192.168.37.133 | FAILED | rc=1 &gt;&gt;
</code></pre><p>　　发现已经没有这个用户了。</p>
<h3 id="11group-模块">11）group 模块</h3>
<p>　　该模块主要用于添加或删除组。<br />
　　常用的选项如下：</p>
<blockquote>
<p><code>gid=</code>　　#设置组的GID号<br />
<code>name=</code>　　#指定组的名称<br />
<code>state=</code>　　#指定组的状态，默认为创建，设置值为<code>absent</code>为删除<br />
<code>system=</code>　　#设置值为<code>yes</code>，表示创建为系统组</p>
</blockquote>
<p>　　举例如下：<br />
<strong>① 创建组</strong></p>
<pre><code>[root@server ~]# ansible web -m group -a 'name=sanguo gid=12222'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;gid&quot;: 12222, 
    &quot;name&quot;: &quot;sanguo&quot;, 
    &quot;state&quot;: &quot;present&quot;, 
    &quot;system&quot;: false
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;gid&quot;: 12222, 
    &quot;name&quot;: &quot;sanguo&quot;, 
    &quot;state&quot;: &quot;present&quot;, 
    &quot;system&quot;: false
}
</code></pre><p>　　创建过后，我们来查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /etc/group | grep 12222' 
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
sanguo❌12222:

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
sanguo❌12222:
</code></pre><p>　　可以看出，我们的组已经创建成功了。<br />
<strong>② 删除组</strong></p>
<pre><code>[root@server ~]# ansible web -m group -a 'name=sanguo state=absent'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;name&quot;: &quot;sanguo&quot;, 
    &quot;state&quot;: &quot;absent&quot;
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;name&quot;: &quot;sanguo&quot;, 
    &quot;state&quot;: &quot;absent&quot;
}
</code></pre><p>　　照例查看一下：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /etc/group | grep 12222' 
192.168.37.122 | FAILED | rc=1 &gt;&gt;

192.168.37.133 | FAILED | rc=1 &gt;&gt;
</code></pre><p>　　已经没有这个组的相关信息了。</p>
<h3 id="12script-模块">12）script 模块</h3>
<p>　　该模块用于将本机的脚本在被管理端的机器上运行。<br />
　　该模块直接指定脚本的路径即可，我们通过例子来看一看到底如何使用的：<br />
　　首先，我们写一个脚本，并给其加上执行权限：</p>
<pre><code>[root@server ~]# vim /tmp/df.sh
	#!/bin/bash

	date &gt;&gt; /tmp/disk_total.log
	df -lh &gt;&gt; /tmp/disk_total.log 
[root@server ~]# chmod +x /tmp/df.sh 
</code></pre><p>　　然后，我们直接运行命令来实现在被管理端执行该脚本：</p>
<pre><code>[root@server ~]# ansible web -m script -a '/tmp/df.sh'
192.168.37.122 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;rc&quot;: 0, 
    &quot;stderr&quot;: &quot;Shared connection to 192.168.37.122 closed.\r\n&quot;, 
    &quot;stdout&quot;: &quot;&quot;, 
    &quot;stdout_lines&quot;: []
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;changed&quot;: true, 
    &quot;rc&quot;: 0, 
    &quot;stderr&quot;: &quot;Shared connection to 192.168.37.133 closed.\r\n&quot;, 
    &quot;stdout&quot;: &quot;&quot;, 
    &quot;stdout_lines&quot;: []
}
</code></pre><p>　　照例查看一下文件内容：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'cat /tmp/disk_total.log'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
Tue Dec  5 15:58:21 CST 2017
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        47G  4.4G   43G  10% /
devtmpfs        978M     0  978M   0% /dev
tmpfs           993M   84K  993M   1% /dev/shm
tmpfs           993M  9.1M  984M   1% /run
tmpfs           993M     0  993M   0% /sys/fs/cgroup
/dev/sda3        47G   33M   47G   1% /app
/dev/sda1       950M  153M  798M  17% /boot
tmpfs           199M   16K  199M   1% /run/user/42
tmpfs           199M     0  199M   0% /run/user/0

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
Tue Dec  5 15:58:21 CST 2017
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        46G  4.1G   40G  10% /
devtmpfs        898M     0  898M   0% /dev
tmpfs           912M   84K  912M   1% /dev/shm
tmpfs           912M  9.0M  903M   1% /run
tmpfs           912M     0  912M   0% /sys/fs/cgroup
/dev/sda3       3.7G   15M  3.4G   1% /app
/dev/sda1       1.9G  141M  1.6G   9% /boot
tmpfs           183M   16K  183M   1% /run/user/42
tmpfs           183M     0  183M   0% /run/user/0
</code></pre><p>　　可以看出已经执行成功了。</p>
<h3 id="13setup-模块">13）setup 模块</h3>
<p>　　该模块主要用于收集信息，是通过调用facts组件来实现的。<br />
　　facts组件是Ansible用于采集被管机器设备信息的一个功能，我们可以使用setup模块查机器的所有facts信息，可以使用filter来查看指定信息。整个facts信息被包装在一个JSON格式的数据结构中，ansible_facts是最上层的值。<br />
　　facts就是变量，内建变量 。每个主机的各种信息，cpu颗数、内存大小等。会存在facts中的某个变量中。调用后返回很多对应主机的信息，在后面的操作中可以根据不同的信息来做不同的操作。如redhat系列用yum安装，而debian系列用apt来安装软件。<br />
<strong>① 查看信息</strong><br />
　　我们可以直接用命令获取到变量的值，具体我们来看看例子：</p>
<pre><code>[root@server ~]# ansible web -m setup -a 'filter=&quot;*mem*&quot;'	#查看内存
192.168.37.122 | SUCCESS =&gt; {
    &quot;ansible_facts&quot;: {
        &quot;ansible_memfree_mb&quot;: 1116, 
        &quot;ansible_memory_mb&quot;: {
            &quot;nocache&quot;: {
                &quot;free&quot;: 1397, 
                &quot;used&quot;: 587
            }, 
            &quot;real&quot;: {
                &quot;free&quot;: 1116, 
                &quot;total&quot;: 1984, 
                &quot;used&quot;: 868
            }, 
            &quot;swap&quot;: {
                &quot;cached&quot;: 0, 
                &quot;free&quot;: 3813, 
                &quot;total&quot;: 3813, 
                &quot;used&quot;: 0
            }
        }, 
        &quot;ansible_memtotal_mb&quot;: 1984
    }, 
    &quot;changed&quot;: false
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;ansible_facts&quot;: {
        &quot;ansible_memfree_mb&quot;: 1203, 
        &quot;ansible_memory_mb&quot;: {
            &quot;nocache&quot;: {
                &quot;free&quot;: 1470, 
                &quot;used&quot;: 353
            }, 
            &quot;real&quot;: {
                &quot;free&quot;: 1203, 
                &quot;total&quot;: 1823, 
                &quot;used&quot;: 620
            }, 
            &quot;swap&quot;: {
                &quot;cached&quot;: 0, 
                &quot;free&quot;: 3813, 
                &quot;total&quot;: 3813, 
                &quot;used&quot;: 0
            }
        }, 
        &quot;ansible_memtotal_mb&quot;: 1823
    }, 
    &quot;changed&quot;: false
}
</code></pre><p>　　我们可以通过命令查看一下内存的大小以确认一下是否一致：</p>
<pre><code>[root@server ~]# ansible web -m shell -a 'free -m'
192.168.37.122 | SUCCESS | rc=0 &gt;&gt;
              total        used        free      shared  buff/cache   available
Mem:           1984         404        1122           9         457        1346
Swap:          3813           0        3813

192.168.37.133 | SUCCESS | rc=0 &gt;&gt;
              total        used        free      shared  buff/cache   available
Mem:           1823         292        1207           9         323        1351
Swap:          3813           0        3813
</code></pre><p>　　可以看出信息是一致的。<br />
<strong>② 保存信息</strong><br />
　　我们的setup模块还有一个很好用的功能就是可以保存我们所筛选的信息至我们的主机上，同时，文件名为我们被管制的主机的IP，这样方便我们知道是哪台机器出的问题。<br />
　　我们可以看一看例子：</p>
<pre><code>[root@server tmp]# ansible web -m setup -a 'filter=&quot;*mem*&quot;' --tree /tmp/facts
192.168.37.122 | SUCCESS =&gt; {
    &quot;ansible_facts&quot;: {
        &quot;ansible_memfree_mb&quot;: 1115, 
        &quot;ansible_memory_mb&quot;: {
            &quot;nocache&quot;: {
                &quot;free&quot;: 1396, 
                &quot;used&quot;: 588
            }, 
            &quot;real&quot;: {
                &quot;free&quot;: 1115, 
                &quot;total&quot;: 1984, 
                &quot;used&quot;: 869
            }, 
            &quot;swap&quot;: {
                &quot;cached&quot;: 0, 
                &quot;free&quot;: 3813, 
                &quot;total&quot;: 3813, 
                &quot;used&quot;: 0
            }
        }, 
        &quot;ansible_memtotal_mb&quot;: 1984
    }, 
    &quot;changed&quot;: false
}
192.168.37.133 | SUCCESS =&gt; {
    &quot;ansible_facts&quot;: {
        &quot;ansible_memfree_mb&quot;: 1199, 
        &quot;ansible_memory_mb&quot;: {
            &quot;nocache&quot;: {
                &quot;free&quot;: 1467, 
                &quot;used&quot;: 356
            }, 
            &quot;real&quot;: {
                &quot;free&quot;: 1199, 
                &quot;total&quot;: 1823, 
                &quot;used&quot;: 624
            }, 
            &quot;swap&quot;: {
                &quot;cached&quot;: 0, 
                &quot;free&quot;: 3813, 
                &quot;total&quot;: 3813, 
                &quot;used&quot;: 0
            }
        }, 
        &quot;ansible_memtotal_mb&quot;: 1823
    }, 
    &quot;changed&quot;: false
}
</code></pre><p>　　然后我们可以去查看一下：</p>
<pre><code>[root@server ~]# cd /tmp/facts/
[root@server facts]# ls
192.168.37.122  192.168.37.133
[root@server facts]# cat 192.168.37.122 
{&quot;ansible_facts&quot;: {&quot;ansible_memfree_mb&quot;: 1115, &quot;ansible_memory_mb&quot;: {&quot;nocache&quot;: {&quot;free&quot;: 1396, &quot;u
</code></pre><h2 id="案例">案例</h2>
<p>廖雪峰的博客系统itranswarp，有ansible部署脚本</p>
<p><a href="https://github.com/michaelliao/itranswarp">https://github.com/michaelliao/itranswarp</a></p>
<h2 id="附件">附件</h2>
<p><p class="md__image">
  <img src="/../../me/ansible/Screenshot%20from%202020-02-11%2012-42-47.png" alt="Screenshot from 2020-02-11 12-42-47"  />
</p></p>
<p><p class="md__image">
  <img src="/../../me/ansible/Screenshot%20from%202020-02-11%2013-02-39.png" alt="Screenshot from 2020-02-11 13-02-39"  />
</p></p>
<p><p class="md__image">
  <img src="/../../me/ansible/Screenshot%20from%202020-02-11%2013-03-27.png" alt="Screenshot from 2020-02-11 13-03-27"  />
</p></p>
  </article>
</div>
      
<div class="grow"></div>
<nav class="pagination-single">
  
    
    <div class="grow"></div>
    
      <a href="http://shaochenfeng.com/linux/docker%E5%AE%B9%E5%99%A8/" title="docker容器" class="pagination-single__right">
        <div class="pagination-single__left-title">docker容器</div>
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M5 13h11.17l-4.88 4.88c-.39.39-.39 1.03 0 1.42.39.39 1.02.39 1.41 0l6.59-6.59c.39-.39.39-1.02 0-1.41l-6.58-6.6c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L16.17 11H5c-.55 0-1 .45-1 1s.45 1 1 1z"/></svg>
        </div>
      </a>
    
  
</nav>


      
    </article>
    
    <section id="list-side" class="r" data-dir="ltr">
      
        <div class="toc">
  <h6 class="toc__label">目录</h6>
  <div class="toc__body">
    <nav id="TableOfContents">
  <ul>
    <li><a href="#安装">安装</a></li>
    <li><a href="#ansible-任务执行模式">ansible 任务执行模式</a></li>
    <li><a href="#配置文件">配置文件</a></li>
    <li><a href="#使用点对点模式">使用点对点模式</a></li>
    <li><a href="#使用剧本模式">使用剧本模式</a></li>
    <li><a href="#常见的命令行操作">常见的命令行操作</a></li>
    <li><a href="#ansible-常用模块">ansible 常用模块</a></li>
    <li><a href="#案例">案例</a></li>
    <li><a href="#附件">附件</a></li>
  </ul>
</nav>
  </div>
</div>
      
    </section>

  </div>
</div>

<script>
  'use strict';
  
  function wrap(el, wrapper) {
    el.parentNode.insertBefore(wrapper, el);
    wrapper.appendChild(el);
  }

  (function () {
    var singleContentsElem = document.querySelector('.single__contents');
    singleContentsElem ? 
    singleContentsElem.querySelectorAll('pre > code').forEach(function(elem) {
      var dataLang = elem.getAttribute('data-lang');
      var dataLangWrapper = document.createElement('div');
      var code = null;
      var codeTitle = null;

      if (dataLang && dataLang.includes(':')) {
        code = dataLang.split(':')[0];
        codeTitle = dataLang.split(':')[1];

        dataLangWrapper.className = 'language-' + code;
        dataLangWrapper.setAttribute('data-lang', codeTitle);

        elem.className = 'language-' + code;
        elem.setAttribute('data-lang', codeTitle);
        elem.setAttribute('id', codeTitle);
      }

      if (!dataLang || codeTitle) {
        wrap(elem.parentNode, dataLangWrapper);
      }

    }) : null;
  })();
  


  
  
  var dollarCodeElem = document.querySelectorAll('div.language-\\$');
  var gtCodeElem = document.querySelectorAll('div.language-\\>');
  
  dollarCodeElem ?
  dollarCodeElem.forEach(function(elem) {
    var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
    lnts ? 
    lnts.forEach(function(lnt) {
      lnt.innerHTML = '$<br/>';
    }) : null;
  }) : null;

  gtCodeElem ?
  gtCodeElem.forEach(function(elem) {
    var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
    lnts ? 
    lnts.forEach(function(lnt) {
      lnt.innerHTML = '><br/>';
    }) : null;
  }) : null;
  
</script>




<script defer src="/js/helper/getParents.min.js"></script>

<script defer src="/js/helper/closest.min.js"></script>

<script defer src="/js/helper/prev.min.js"></script>

<script defer src="/js/helper/prop.min.js"></script>

<script defer src="/js/helper/fadeinout.min.js"></script>












<script>
  document.addEventListener('DOMContentLoaded', function () {
    'use strict';
    
    
    var tables = document.querySelectorAll('.single__contents > table');
    for (let i = 0; i < tables.length; i++) {
      var table = tables[i];
      var wrapper = document.createElement('div');
      wrapper.className = 'table-wrapper';
      table.parentElement.replaceChild(wrapper, table);
      wrapper.appendChild(table);
    }
    


    
    
    
    var lib = JSON.parse("null");

    if (lib && lib.includes('mermaid')) {
      var themeVariant = localStorage.getItem('theme') || 'light';

      if (themeVariant === "dark") {
        mermaid.initialize({ theme: 'dark' });
      } else {
        mermaid.initialize({ theme: 'default' });
      }
      
      var mermaids = [];
      [].push.apply(mermaids, document.getElementsByClassName('language-mermaid'));
      mermaids.forEach(function(elem) {
        var elemParentNode = elem.parentNode;

        if (elemParentNode !== document.body) {
          elemParentNode.parentNode.insertBefore(elem, elemParentNode);
          elemParentNode.parentNode.removeChild(elemParentNode);
        }

        var newElemWrapper = document.createElement('div');
        newElemWrapper.classList.add('mermaid');
        newElemWrapper.innerHTML = elem.innerHTML;
        elem.replaceWith(newElemWrapper);
      });
    }
    
    

    
    if (lib && lib.includes('katex')) {
      var mathElements = document.getElementsByClassName('math');
      var options = {
        delimiters: [
          { left: "$$", right: "$$", display: true },
          { left: "\\[", right: "\\]", display: true },
          { left: "$", right: "$", display: false },
          { left: "\\(", right: "\\)", display: false }
        ],
      };

      renderMathInElement(document.querySelector('.single__contents'), options);
    }
    


    
    if (lib && lib.includes('flowchartjs')) {
      
      var options = JSON.parse("{\"arrow-end\":\"block\",\"element-color\":\"black\",\"fill\":\"white\",\"flowstate\":{\"approved\":{\"fill\":\"#58C4A3\",\"font-size\":12,\"no-text\":\"n/a\",\"yes-text\":\"APPROVED\"},\"current\":{\"fill\":\"yellow\",\"font-color\":\"red\",\"font-weight\":\"bold\"},\"future\":{\"fill\":\"#FFFF99\"},\"invalid\":{\"fill\":\"#444444\"},\"past\":{\"fill\":\"#CCCCCC\",\"font-size\":12},\"rejected\":{\"fill\":\"#C45879\",\"font-size\":12,\"no-text\":\"REJECTED\",\"yes-text\":\"n/a\"},\"request\":{\"fill\":\"blue\"}},\"font-color\":\"black\",\"font-size\":14,\"line-color\":\"black\",\"line-length\":50,\"line-width\":3,\"no-text\":\"no\",\"scale\":1,\"symbols\":{\"end\":{\"class\":\"end-element\"},\"start\":{\"element-color\":\"green\",\"fill\":\"yellow\",\"font-color\":\"red\"}},\"text-margin\":10,\"x\":0,\"y\":0,\"yes-text\":\"yes\"}");
      var jsonContent = null;

      var flowchartPrefix = "language-flowchart";
      var index = 0;
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + flowchartPrefix + "]"), function(x){
          x.style.display = 'none'
          x.parentNode.style.backgroundColor = "transparent"
          jsonContent = x.innerText;

          var node0 = document.createElement('div');
          node0.id = 'flowchart' + index;
          x.parentNode.insertBefore(node0, x);

          var diagram = flowchart.parse(jsonContent);
          diagram.drawSVG("flowchart"+index, options);

          index +=1;
      });      
    }
    


    
    if (lib && lib.includes('chart')) {
      var borderColor = "#666";
      var bgColor = "#ddd";
      var borderWidth = 2;

      Chart.defaults.global.elements.rectangle.borderWidth = borderWidth;
      Chart.defaults.global.elements.rectangle.borderColor = borderColor;
      Chart.defaults.global.elements.rectangle.backgroundColor = bgColor;

      Chart.defaults.global.elements.line.borderWidth = borderWidth;
      Chart.defaults.global.elements.line.borderColor = borderColor;
      Chart.defaults.global.elements.line.backgroundColor = bgColor;

      Chart.defaults.global.elements.point.borderWidth = borderWidth;
      Chart.defaults.global.elements.point.borderColor = borderColor;
      Chart.defaults.global.elements.point.backgroundColor = bgColor;

      var chartPrefix = "language-chart";
      var index = 0;
      var jsonContent = null;

      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + chartPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('canvas');
        var source = null;
        node0.height = 200;
        node0.style.height = 200;
        node0.id = 'myChart' + index;
        source = JSON.parse(jsonContent);
        x.parentNode.insertBefore(node0, x);
        var ctx = document.getElementById('myChart' + index).getContext('2d');
        var myChart = new Chart(ctx, source);
        index += 1;
      });            
    }
    


    
    if (lib && lib.includes('viz')) {
      var vizPrefix = "language-viz-";
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + vizPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        var engine;
        x.getAttribute("class").split(" ").forEach(function (cls) {
          if (cls.startsWith(vizPrefix)) {
            engine = cls.substr(vizPrefix.length);
          }
        });
        var viz = new Viz();
        viz.renderSVGElement(x.innerText, { engine: engine })
          .then(function (element) {
            element.style.width = "100%";
            x.parentNode.insertBefore(element, x);
          })
      });
    }
    
    
  });
</script>

<script>
  var listSide = document.getElementById('list-side');
  var listMain = document.getElementById('list-main');
  var singleMenu = document.getElementById('single-menu');
  var switchElem = document.querySelector('.switch');
  var wideViewAsDefault = JSON.parse("null");
  
  enquire.register("screen and (max-width:1280px)", {
    match: function () {
      if (wideViewAsDefault) {
        singleMenu.className = 'l';  
        listMain.className = 'mr';
        listSide.className = 'hide';
      } else {
        singleMenu.className = 'l';
        listMain.className = 'm';
        listSide.className = 'r';
      }
    },
    unmatch: function () {
      if (wideViewAsDefault) {
        singleMenu.className = 'l';
        listMain.className = 'mr';
        listSide.className = 'hide';
      } else {
        listSide.className = 'r';
        listMain.className = 'm';
        singleMenu.className = 'l';
      }
    },
  }).register("screen and (max-width:960px)", {
    match: function () {
      singleMenu.className = 'l';
      listMain.className = 'mr';
      listSide.className = 'hide';
      switchElem.className = 'hide';
    },
    unmatch: function () {
      if (wideViewAsDefault) {
        singleMenu.className = 'l';
        listMain.className = 'mr';
        listSide.className = 'hide';
      } else {
        singleMenu.className = 'l';
        listMain.className = 'm';
        listSide.className = 'r';
      }
      switchElem.className = 'switch';
    },
  }).register("screen and (max-width:600px)", {
    match: function () {
      listSide.className = 'hide';
      listMain.className = 'lmr';
      singleMenu.className = 'hide';
      switchElem.className = 'hide';
    },
    unmatch: function () {
      listSide.className = 'hide';
      listMain.className = 'mr';
      singleMenu.className = 'l';
      switchElem.className = 'hide';
    },
  });
</script>

        
<div class="bot">
  <footer class="footer">
    <div class="divider">
      <div class="lmr">
        
          <p class="caption">
            <a href="https://beian.miit.gov.cn/" target="_blank">冀ICP备18002899号</a>    ©2021, All Rights Reserved
          </p>
          
        
      </div>
    </div>
  </footer>
</div>

    </div>

</body>

</html>